package com.xzy.sms.core.adapter.impl.nw;

import java.io.IOException;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.xzy.sms.core.adapter.SendSmsAdapter;
import com.xzy.sms.core.entity.SendContext;
import com.xzy.sms.exception.SendSmsException;
import com.xzy.sms.web.domain.entity.ChannelConfig;

/**
 * @desc 
 * @author wjw
 * @time 2017年11月16日下午3:29:28
 */
public class NwSendSmsAdapter implements SendSmsAdapter {
    
    /** FIXME */
    private final String WDSL = "?wdsl";
    
    /** FIXME */
    private final int WDSL_LEN = WDSL.length();
    
    /** 向webservice服务提交的内容 */
    private final String SEND_CONTENT = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><Post xmlns=\"http://www.139130.net\" "
        + " xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"
        + "<account>%s</account><password>%s</password><mtpack><uuid>00000000-0000-0000-0000-000000000000</uuid><batchID>%s</batchID>"
        + "<batchName>%s</batchName><sendType>0</sendType><msgType>1</msgType><msgs>%s</msgs>"
        + "<bizType>0</bizType><distinctFlag>false</distinctFlag><scheduleTime>0</scheduleTime><deadline>0</deadline></mtpack></Post></s:Body></s:Envelope>";
        
    /** 单条短信内容 */
    private final String SMS_CONTENT = "<MessageData><Phone>%s</Phone><Content>%s</Content><vipFlag>false</vipFlag></MessageData>";
    
    /** 返回结果的正则表达式 */
    private final Pattern RESULT_REGX = Pattern.compile("<result>([^<]+)</result>\\s*<uuid>[^<]+</uuid>\\s*<message>([^<]+)</message>",
        Pattern.DOTALL);
        
    /** 短信编码 */
    private final static String UTF8 = "utf-8";
    
    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     *
     * @param smsContext xx
     */
    @Override
    public void sendSms(SendContext smsContext) throws SendSmsException {
        ChannelConfig cc = smsContext.getChannelConfig();
        String uri = cc.getUrl();
        if (StringUtils.isEmpty(uri) || !uri.startsWith("http://")) {
            throw new SendSmsException("发送短信的网关Webservice地址没有配置正确 ： " + uri);
        } else if (StringUtils.endsWithIgnoreCase(uri, WDSL)) {
            uri = uri.substring(0, uri.length() - WDSL_LEN);
        }
        
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost request = new HttpPost(uri);
        request.setHeader("Content-Type", "text/xml; charset=utf-8");
        CloseableHttpResponse response = null;
        
        try {
            request.setEntity(new StringEntity(builderPayload(smsContext), UTF8));
            response = httpClient.execute(request);
            if (response.getStatusLine().getStatusCode() != 200) {
                throw new RuntimeException("短信发送异常,接收到短信服务器返回状态：" + response.getStatusLine().getStatusCode());
            }
            HttpEntity content = response.getEntity();
            String result = EntityUtils.toString(content);
            Matcher matcher = RESULT_REGX.matcher(result);
            if (matcher == null || !matcher.find()) {
                throw new RuntimeException("短信发送异常,接收到短信服务器返回未知格式的结果");
            }
            String code = matcher.group(1);
            String message = matcher.group(2);
            if (!"0".equals(code)) {
                throw new RuntimeException("短信网关返回意外结果,原因: " + message + " 原始结果：" + result);
            }
        } catch (ParseException | IOException ex) {
            throw new RuntimeException("短信发送异常", ex);
        } finally {
            HttpClientUtils.closeQuietly(response);
        }
    }
    
    /**
     * FIXME 方法注释信息(此标记由Eclipse自动生成,请填写注释信息删除此标记)
     * 
     * @param smsContext xx
     * @return xx
     */
    private String builderPayload(SendContext smsContext) {
        ChannelConfig cc = smsContext.getChannelConfig();
        String batchId = UUID.randomUUID().toString();
        String batchName = String.format("EIM_%s", System.currentTimeMillis());
        String smsContent = String.format(SMS_CONTENT, StringEscapeUtils.escapeXml(smsContext.getMobile()),
            StringEscapeUtils.escapeXml(smsContext.getContent()));
        return String.format(SEND_CONTENT, StringEscapeUtils.escapeXml(cc.getAccount()), StringEscapeUtils.escapeXml(cc.getPassword()), batchId,
            batchName, smsContent);
    }
}
